﻿//-----------------------------------------------------------------------
// <copyright file="FormMenu.cs" company="Istante srl">
//     Copyright (c) Istante srl. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Linq;
using ClearVss.Entities;
using System.ComponentModel;

namespace ClearVss
{
    /// <summary>
    /// Form that find adn remove any refrences to the Vss inside a direcotry and it's descendant
    /// </summary>
    public partial class FormMenu : Form
    {
        /// <summary> Indicate the numbers of lines logged to the textBox </summary>
        private int linesLogged = 0;

        /// <summary> List of message log </summary>
        private BindingList<MessageLog> logList = null;

        /// <summary>
        /// Initializes a new instance of the FormMenu class
        /// </summary>
        public FormMenu()
        {
            InitializeComponent();
            this.Init();
        }

        /// <summary>
        /// Private initialization
        /// </summary>
        private void Init()
        {
            verToolStripMenuItem.Text = string.Format("Version: {0}", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
            logList = new BindingList<MessageLog>();
            dataGridView1.DataSource = logList;
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            dataGridView1.Columns[1].FillWeight = 400;

            toolStripStatusLabelLog.Text = string.Empty;
        }

        /// <summary>
        /// Remove Visual Souce Safe Files, modify solution and project file
        /// Reset readonly attribute
        /// </summary>
        private void Clear()
        {
            if (folderBrowserDialogVss.ShowDialog() == DialogResult.OK)
            {
                Cursor = Cursors.WaitCursor;
                try
                {
                    string dir = folderBrowserDialogVss.SelectedPath;
                    toolStripStatusLabelLog.Text = string.Empty;
                    logList.Clear();
                    this.RemoveVssFiles(dir);
                    this.RemoveVssFromAllProjects(dir);
                    this.RemoveVssFromAllSolutions(dir);
                    this.RemoveVssFromAllSetupProjects(dir);
                    if (resetToolStripMenuItem.Checked)
                    {
                        this.RemoveReadOnlyFromFiles(dir);
                    }

                    toolStripStatusLabelLog.Text = "Done!";
                }
                finally
                {
                    Cursor = Cursors.Default;
                }
            }
        }

        /// <summary>
        /// Remove ReadOnly From Files
        /// </summary>
        /// <param name="aPath">Solution's Path</param>
        private void RemoveReadOnlyFromFiles(string aPath)
        {
            List<string> fileList = Directory.GetFiles(aPath, "*.*", SearchOption.AllDirectories).ToList();
            foreach (string item in fileList)
            {
                File.SetAttributes(item, FileAttributes.Normal);
                this.LogOperation(new MessageLog { FileName = item, Message = "File", Operation = "Set attribute" });
            }
        }

        /// <summary>
        /// Remove Vss files with extension .scc and .vssscc
        /// </summary>
        /// <param name="aPath">Path of solution</param>
        private void RemoveVssFiles(string aPath)
        {
            List<string> fileList = Directory.GetFiles(aPath, "*.scc", SearchOption.AllDirectories).ToList();
            fileList.AddRange(Directory.GetFiles(aPath, "*.vssscc", SearchOption.AllDirectories).ToList());
            fileList.AddRange(Directory.GetFiles(aPath, "*.vspscc", SearchOption.AllDirectories).ToList());
            foreach (string item in fileList)
            {
                File.SetAttributes(item, FileAttributes.Normal);
                File.Delete(item);
                this.LogOperation(new MessageLog { FileName = item, Message = "Vss file", Operation = "Deleted" });
            }
        }

        /// <summary>
        /// Search for solution file and remove section of Vss
        /// </summary>
        /// <param name="aPath">Path of solution</param>
        private void RemoveVssFromAllSolutions(string aPath)
        {
            string[] projectList = Directory.GetFiles(aPath, "*.sln", SearchOption.AllDirectories);
            foreach (string item in projectList)
            {
                if (this.RemoveVssFromSolution(item))
                {
                    this.LogOperation(new MessageLog { FileName = item, Message = "Solution File", Operation = "Modified" });
                }
            }
        }

        /// <summary>
        /// Removes the VSS entries from all setup project files.
        /// </summary>
        /// <param name="aPath">Path of solution</param>
        private void RemoveVssFromAllSetupProjects(string aPath)
        {
            string[] projectList = Directory.GetFiles(aPath, "*.vdproj", SearchOption.AllDirectories);
            foreach (string item in projectList)
            {
                if (this.RemoveVssFromSetupProject(item))
                {
                    this.LogOperation(new MessageLog { FileName = item, Message = "Vss setup file", Operation = "Modified" });
                }
            }
        }

        /// <summary>
        /// Search for project file and remove section of Vss
        /// </summary>
        /// <param name="aPath">Path of solution</param>
        private void RemoveVssFromAllProjects(string aPath)
        {
            string[] vbcs = new string[] { "*.csproj", "*.vbproj" };
            foreach (string proj in vbcs)
            {
                string[] projectList = Directory.GetFiles(aPath, proj, SearchOption.AllDirectories);
                foreach (string item in projectList)
                {
                    if (this.RemoveVssFromProject(item))
                    {
                        this.LogOperation(new MessageLog { FileName = item, Message = "Project file", Operation = "Modified" });
                    }
                }
            }
        }

        /// <summary>
        /// Find and remove inside project file the sections of vss 
        /// </summary>
        /// <param name="aFile">Project file</param>
        /// <returns>True if find</returns>
        private bool RemoveVssFromProject(string aFile)
        {
            bool find = false;
            File.SetAttributes(aFile, FileAttributes.Normal);
            XElement elem = XElement.Load(aFile);

            XElement[] itemsDelete = (from item in elem.Descendants()
                                      where ((item.Name.LocalName == "SccProjectName") ||
                                  (item.Name.LocalName == "SccLocalPath") ||
                                  (item.Name.LocalName == "SccAuxPath") ||
                                  (item.Name.LocalName == "SccProvider"))
                                      select item).ToArray();

            foreach (XElement item in itemsDelete)
            {
                find = true;
                item.Remove();
            }

            if (find)
            {
                elem.Save(aFile);
            }

            return find;
        }

        /// <summary>
        /// Find and remove inside solution file the sections of vss
        /// </summary>
        /// <param name="aFile">Solution file</param>
        /// <returns>True if removed</returns>
        private bool RemoveVssFromSetupProject(string aFile)
        {
            bool modified = false;
            File.SetAttributes(aFile, FileAttributes.Normal);

            List<string> solutionFile = new List<string>(File.ReadAllLines(aFile));

            // Check for source control related lines
            for (int i = 0; i < solutionFile.Count; i++)
            {
                if (solutionFile[i].Contains("SccProjectName"))
                {
                    solutionFile.RemoveAt(i);
                    modified = true;
                }

                if (solutionFile[i].Contains("SccAuxPath"))
                {
                    solutionFile.RemoveAt(i);
                    modified = true;
                }

                if (solutionFile[i].Contains("SccLocalPath"))
                {
                    solutionFile.RemoveAt(i);
                    modified = true;
                }

                if (solutionFile[i].Contains("SccProvider"))
                {
                    solutionFile.RemoveAt(i);
                    modified = true;
                }
            }

            if (modified)
            {
                File.WriteAllLines(aFile, solutionFile.ToArray());
            }

            return modified;
        }

        /// <summary>
        /// Find and remove inside solution file the sections of vss
        /// </summary>
        /// <param name="aFile">Solution file</param>
        /// <returns>True if find SourceSafe tag</returns>
        private bool RemoveVssFromSolution(string aFile)
        {
            File.SetAttributes(aFile, FileAttributes.Normal);

            const string EndString = "EndGlobalSection";
            const string StartString = "GlobalSection(SourceCodeControl) = preSolution";

            string solutionFile = File.ReadAllText(aFile);
            int start = solutionFile.IndexOf(StartString);
            if (start > -1)
            {
                int end = solutionFile.IndexOf(EndString) + EndString.Length;
                solutionFile = solutionFile.Remove(start, (end - start) + 1);
                File.WriteAllText(aFile, solutionFile);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Log operation to grid
        /// </summary>
        /// <param name="aMessage">Message to log</param>
        private void LogOperation(MessageLog aMessage)
        {
            logList.Add(aMessage);
        }

        /// <summary>
        /// Remove Visual Source Safe files
        /// </summary>
        /// <param name="sender">Object source</param>
        /// <param name="e">Object paramters</param>
        private void RemoveVssToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Clear();
        }

        /// <summary>
        /// Open new web page
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Object parameters</param>
        private void WebSiteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.istante.info");
        }
    }
}
